
#pragma once

#include <TextureItem.h>
#include <vector>
#include <WTypes.h>
#include <d3dx9.h>
#include <d3dapp.h>
#include "IArchive.h"
#include "goodlinklist.h"
#include "d3dAppForm.h"

#define FPSMOD 160// nobody know why.
#define GXRELEASE(_p) do { if ((_p) != NULL) {(_p)->Release(); (_p) = NULL;} } while (0)

#define D3DDEVICE CD3DAppForm::GetD3D()->m_pd3dDevice

enum _CHATYPE
{
	_MAN,// M
	_WOMEN,// F
	_NPC,//N
	_PET,//P
	_MAX_CHARTYPE,
};

enum _SKELETONMESHTYPE
{
	_SMESH_GENERAL,
	_SMESH_FACE,
	_SMESH_WEAPON
};

#define MESH_PART_COUNT 7
enum _PART
{
	_HAIR, //H
	_FACE, //F
	_BODY, //C
	_HAND, //A
	_FOOT, //B
	_CLOCK,//M
	_ARM,//W
	_SET,//L
	_MAX_PART,
};
enum _CLASSTYPE
{
	_CLASS_KNIFE, //B
	_CLASS_SWORD, //S
	_CLASS_HAND, //H
	_CLASS_ROD, //C
	_CLASS_FAN, //F
	_CLASS_EMPTY, //E
	_CLASS_NPC, //P
	_CLASS_MONSTER, //M
	_CLASS_BOOSMONSTER, //L
	_CLASS_MAX,
};

enum _AniPlayOption// now nobody know opt0,1,4
{
	_PlayOpt0 = 0,
	_PlayOpt1 = 1,
	_NotLoop  = 2,
	_PlayOpt4 = 4
};

enum
{
	_NPCINDEX = 10000,
	_NPCINDEX_NPC = _NPCINDEX,
	_NPCINDEX_MONSTER = _NPCINDEX_NPC + _NPCINDEX,
	_NPCINDEX_BOSSMONSTER = _NPCINDEX_MONSTER + _NPCINDEX,
};


enum eAniAction
{
	ANIACTION_STAND,
	ANIACTION_WALK,
	ANIACTION_RUN,
	ANIACTION_MAX,
};

enum eAniIndex
{
	ANIINDEX_GSTAND = 5,
	ANIINDEX_ASTAND = 7,
	ANIINDEX_GWALK = 12,
	ANIINDEX_AWALK = 13,
	ANIINDEX_GRUN = 14,
	ANIINDEX_ARUN = 15,

	ANIINDEX_DAMAGE = 8,
	ANIINDEX_CRITICALDAMAGE = 9,
	ANIINDEX_DEAD = 10,
	ANIINDEX_CRITICALDEAD = 11,
};

enum eNpcAction
{
	NPC_ACT_STAND = 1,
	NPC_ACT_WALK,
	NPC_ACT_RUN,
	NPC_ACT_MOVE,	
	NPC_ACT_ATTACK,
	NPC_ACT_DEAD,
	NPC_ACT_DAMAGE,
};
enum eNameShare
{
	_NAME_SHARE_NORMAL = 0,
	_NAME_SHARE_CHARTYPE
};

static int GetSkMeshTypeFormMeshPart(const int& iPart)
{
	if (iPart == _FACE)
	{
		return _SMESH_FACE;
	}
	else if (iPart == _ARM)
	{
		return _SMESH_WEAPON;
	}
	else
	{
		return _SMESH_GENERAL;
	}
}

static int GetSkAinPartFormMeshType(const int& iType)
{
	if (iType == _SMESH_FACE)
	{
		return _FACE;
	}
	else if (iType == _SMESH_WEAPON)
	{
		return _ARM;
	}
	else
	{
		return _BODY;
	}
}
enum _AniEventFLag{_FLAG_ANI_0 = 0,_FLAG_ANI_1};
enum _AniEventType{_EVENT_HITSTART = 0,_EVENT_HITEND,_EVENT_WEAPONCHANGE, _EVENT_SOUND, _EVENT_EFFECT };
enum Old_AniEventType
{
	Event_HitPoint,
	Event_Sound,
	Event_Effect,
};

class _AnimEvent : public CGLLNode
{
public:
	_AnimEvent() : m_fTime(0.0f),m_byEventType(0),m_dwData(0),m_byFlag(_FLAG_ANI_0)
	{
	}
	~_AnimEvent()
	{
	}

	void Serial(CIArchive& ar)
	{
		ar.Serial((char*)this,sizeof(_AnimEvent));			
	}

	float m_fTime;
	DWORD m_dwData;
	BYTE  m_byEventType;
	BYTE  m_byFlag;
};

using namespace std;
struct _PosKey
{
	void Serial(CIArchive& ar)
	{
		ar.Serial((char*)this,sizeof(_PosKey));
	}

	float fTime;
	D3DXVECTOR3 vPos;
};
struct _RotateKey
{
	void Serial(CIArchive& ar)
	{
		ar.Serial((char*)this,sizeof(_RotateKey));
	}
	float fTime;
	D3DXQUATERNION quat;
};

struct _ModelRCDes
{
	_ModelRCDes(const int& ichartype , const int& iparttype,const int& iclass,const int& index = 0,const int& indexex = 0) 
		:iCharType(ichartype),  iPartType(iparttype),iClass(iclass),iIndex( index ),iIndexEX(indexex),iNameShare(0)
	{

	}
	_ModelRCDes() :iCharType(0),  iPartType(0),iClass(0),iIndex( 0 ),iIndexEX(0),iNameShare(0)
	{

	}

	int iCharType;	
	int iPartType;//part or bone type
	int iClass;//class = bone type or kind type 
	int iIndex;

	int iIndexEX;//only use at RC_ID_NPCTEXANDANI
	int iNameShare;
};
static void GetNPCRCDesByIndex( _ModelRCDes& des, const int& iIndex )
{
	des.iCharType = _NPC;
	des.iPartType = _BODY;
	if ( iIndex < _NPCINDEX_MONSTER )
	{
		des.iIndex = iIndex - _NPCINDEX_NPC;
		des.iClass = _CLASS_NPC;
	}
	else if ( iIndex < _NPCINDEX_BOSSMONSTER )
	{
		des.iIndex = iIndex - _NPCINDEX_MONSTER;
		des.iClass = _CLASS_MONSTER;
	}
	else
	{
		des.iIndex = iIndex - _NPCINDEX_BOSSMONSTER;
		des.iClass = _CLASS_BOOSMONSTER;
	}
}

#define SERIALMATR(ar,mat) ar.Serial((char*)&mat,sizeof(D3DXMATRIX))
#define SERIALVECTER3(ar,vec) ar.Serial((char*)&vec,sizeof(D3DXVECTOR3))

template<class T>
void SerialGList(CIArchive& ar,CGLinkedList<T*>& list)
{
	if(ar.IsReading())
	{
		unsigned short u2Len;		
		ar.Serial(u2Len);

		for(int i = 0; i < u2Len; i++)
		{
			T* t = new T;
			ar.Serial(*t);
			list.AddTail(t);					
		}
	}
	else
	{
		unsigned short u2Len = list.GetCount();
		ar.Serial(u2Len);

		T* t = NULL;
		GPOS pos = list;
		while (pos)
		{
			t = list.GetNext(pos);
			ar.Serial(*t);
		}
	}
}

class CModelRCBase
{
public:
	virtual void Serial(CIArchive& ar) = 0;
};
